\def\minorsect#1#2{\section{\ttit{#1~~~~}#2}}
\def\majorsect#1#2{\section{\ttit{#1~~~~}#2}}
\def\elementgenerator{~~$\ddagger$}
\maketitle{SPHIGS for ANSI-C ~~~~ (v0.8, 25 Nov 90)}
\itit{\centerline{David Frederick Sklar}}
\newpar
The Simple Programmer's Hierarchical Graphics 
Standard is composed of a library
of functions, and a
header file (``sphigs.h'') that defines custom data types and constants, and
which prototypes all SPHIGS routines.  This paper is a complete but
\slantit{extremely terse} description 
of the ANSI-C binding.  You must read Chapter 7 of
\itit{Computer Graphics --- Principles and Practice} (Foley, van Dam, Feiner,
and Hughes, Addison-Wesley, 1990) for a full description of SPHIGS.
NOTE: SPHIGS requires the SRGP library.


\bigskip

\item{0)} Comparison with Textbook Specification

\newdisplay

\item{1)} States of the System
\itemmm{1)} initializing the system
\itemmm{2)} controlling screen regeneration

\newdisplay

\item{2)} Maintenance of the Structure Database
\itemmm{1)} macroscopic editing
\itemmm{2)} intra-structure editing

\newdisplay

\item{3)} Coordinate Systems
\itemmm{1)} geometric data types
\itemmm{2)} viewing transformations
\itemmm{3)} modeling transformations

\newdisplay

\item{4)} Color and Shading

\newdisplay

\item{5)} Creation of Graphics Objects
\itemmm{1)} polyLine
\itemmm{2)} polyMarker
\itemmm{3)} text
\itemmm{4)} fill area
\itemmm{5)} polyhedron
\itemmm{6)} rendering modes
\itemmm{7)} execution of subordinate structures

\newdisplay

\item{6)} Dynamic Invisibility and Highlighting

\newdisplay

\item{7)} Input
\itemmm{1)} control of input devices
\itemmm{2)} pick correlation

\newdisplay

\item{8)} Control of Table Sizes


\majorsect{0}{Comparison with Textbook Description}
This section describes how SPHIGS differs from its textbook description, lists
features that are not currently supported but will be supported in future
releases, and lists currently known bugs.

\newpar Viewports:  
In the textbook figures, viewport boundaries were depicted via dashed
rectangular outlines.  This has been deemed too obtrusive for practical use and
has been replaced by a background color --- thus, SPHIGS viewports are opaque
(a violation of the PHIGS standard).  The application can specify a different
background color for each view.  The default color is white, meaning the
viewport boundary will not be obvious.  It is suggested that extremely light
pastel-ish colors be used.  (NOTE: unfortunately, there is currently no method
for depicting viewport boundaries on black-and-white systems.)  Overlapping
viewports should be avoided.

\newpar
Rendering and Color: The FLAT and GOURAUD rendering modes are not currently
supported; LIT\_FLAT is the current ``quality'' rendering mode.  The textbook
did not describe how colors are assigned to objects for the purposes of shaded
rendering in the LIT\_FLAT rendering mode, nor did it describe how simulated
shading is achieved on monochrome implementations.  See section 4.

\newpar
SPHIGS in a windowing environment:  When run on X11 or the Macintosh, the
SPHIGS ``screen'' appears in a window whose size is determined by the
application at initialization time and may be changed by the 
user via a window manager action.

\newpar
Matrices for viewing/modeling:  If you choose to examine the actual matrices
created and manipulated by SPHIGS, don't expect them to correlate with the
matrices you would obtain by following the instructions in Chapters 5 and 6.
They will in fact be the transpose matrices of the ones you would expect.
(SPHIGS' internal linear algebra package uses row vectors instead of
column vectors.)  As a result, when you request preconcatenation, 
SPHIGS internally postconcatenates, and vice versa.

\newpar
\boldit{Viewing BUG!}  When you call 
\ttit{SPH\_evaluateViewMappingMatrix} with a projection type of ORTHOGRAPHIC,
it is possible that the front and back clipping-planes distances you specify in
that call will be lost.  The problem has a simple avoidance mechanism:  if you
always call \ttit{SPH\_setViewRepresentation} immediately after evaluating the
view matrices, the problem never occurs.

\newpar
Subroutine specifications (calling sequence, return value, existence):
Textbook specifications are no
longer valid for SPH\_set\-Rendering\-Mode and for all matrix-calculation
commands (SPH\_scale, etc.)  Also, the subroutine SPH\_copyStructure does not
yet exist.

\newpar
Input:  Pick correlation is currently supported only for polyhedra and fill
area primitives.

\newpar
Name sets for highlighting and invisibility:  Not supported in this version!

\newpar
Fill areas:  They are supported but have not been tested well.  It appears they
may not be sorted correctly with polyhedra in LIT\_FLAT mode.  Moreover, they
(like polyhedron facets) have a visible ``outside'' and an invisible
``inside''; thus, they disappear completely when viewed from one
side, which is quite unintuitive.

\newpar
Fill areas and polyhedron faces: \boldit{MUST BE CONVEX!}  No exceptions!

\newpar
Modeling: Although certainly a single scene should be able to ``contain'' both
solid objects (e.g., polyhedra) and non-solid objects (e.g., lines, text), the
current version of SPHIGS' LIT\_FLAT rendering mode does not handle this well.
All non-solid objects are drawn first, and then the fill areas and polyhedra
facets are drawn back to front.  A line may thus be covered by a facet even
though it is in front.  It is thus strongly recommended that you do not mix
polyhedra and any other types of objects together in a single scene if you wish
to view it using LIT\_FLAT rendering mode.

\newpar
Shaded rendering: In this mode (LIT\_FLAT), SPHIGS must perform a ``z-sort'' to
determine the order in which the faces should be drawn.  The z-sort algorithm
in this version of SPHIGS is relatively stable, but there are bugs that occur,
usually when an edge of one face is coplanar with another face.
\boldit{Moreover, this version of SPHIGS does NOT handle faces that intersect
and faces that are non-convex.}



\majorsect{1}{States of the System}
SPHIGS must be enabled before use, and disabled after use.  At any time, SPHIGS
is in exactly one of the following three operating states:
\bullitem SPHIGS disabled (initial state)
\bullitem SPHIGS enabled, no structure open
\bullitem SPHIGS enabled, structure open


\minorsect{1.1}{initializing the system}
\newsynopsis
void SPH_begin (int width, int height, int planecount, int shadecount);
\endsynopsis
This routine initializes SPHIGS and SRGP, and places SPHIGS in the
enabled/no-structure-open state.  The virtual-screen window is opened, with
its initial dimensions (measure in pixels) determined by the first two
parameters.
(It can be resized by the user with a window manager, if the underlying SRGP
platform supports that functionality.)
The NPC ``unit extent'' (0.0 to 1.0 on both x and y) will map to the largest
square that fits in this area.

\newpar
The last two parameters allow the application to request color resources.  This
is explained in section 4.


\nextsynopsis
void SPH_end (void)
\endsynopsis
The virtual screen window is closed, and SPHIGS enters the disabled state.




\minorsect{1.2}{controlling screen regeneration}
Whenever the application changes the structure database, SPHIGS regenerates the
screen image immediately
\boldit{unless} the implicit-regeneration mode has been set to 
\ttit{SUPPRESSED}.  Its
default value is \ttit{ALLOWED}.  When implicit regeneration is suppressed,
regeneration can be explicitly forced via the second function below.
Otherwise, regeneration occurs when the implicit regeneration mode is restored
to \ttit{ALLOWED}.
\begincode
typedef enum \lb{}SUPPRESSED, ALLOWED\rb regenMode;
void SPH_setImplicitRegenerationMode (regenMode)
void SPH_regenerateScreen (void)
\endcode



\majorsect{2}{Maintenance of the Structure Database}
The structure database is composed of two parts:

\bullitem Conceptually, a fixed number of structures exist in the universe, all
initially empty.  They are indexed by the numbers 0 through
\ttit{MAX\_STRUCTURE\_ID.}  Because a structure may invoke other
structures, this set of structures actually is a set of interlocking
DAGs (directed acyclic graphs) that we call \boldit{networks.}

\bullitem A \itit{view table} having a fixed number of \itit{views}
exists; the views are indexed by the numbers 0 through
\ttit{MAX\_VIEW\_INDEX.}  Each view includes 0 or more references
to networks; a single network can be referenced by more than
one view.  Not all networks are referenced.  Those that are referenced
are said to be \itit{posted} and are therefore potentially visible.

\newpar
There are two genres of editing:

\bullitem \boldit{macro-structure editing} of the structure database:
posting/unposting structures, deleting structures and networks, etc.

\bullitem \boldit{intra-structure editing:} modification
of the contents of a single structure




\minorsect{2.1}{macro-structure editing}
The following functions post and unpost.  They may be called only when there
is no open structure.  The screen is regenerated immediately unless
automatic regeneration is disabled.
\begincode
typedef int structure_ID, view_ID;
void SPH_postRoot (structure_ID, view_ID);
void SPH_unpostRoot (structure_ID, view_ID);
void SPH_unpostAllRoots (view_ID);
\endcode



\minorsect{2.2}{intra-structure editing}
One must open a structure in order to edit it.  Only one structure may
be opened at any time.  All structures exist from time zero; one never
\slantit{creates} a structure, one merely opens an empty structure and edits
it.  The editing operations are not considered ``official'' until the
structure is closed, so screen updating is not performed while the
structure is open.
\begincode
void SPH_openStructure (structure_ID);
void SPH_closeStructure (void);
\endcode

\newpar
When a structure is opened, the element pointer is set to point to the very
last element in the structure.  Since elements are indexed by ascending
integers, starting with 1, this means the element pointer is initialized to $N$
(where $N$ is the number of elements in the structure).  If the structure being
opened is empty, the element pointer is initialized to 0.  The element pointer
may be moved via the following functions.  Movement to index 0 is useful for
inserting new elements at the very beginning of a non-empty structure.
Movement to an index which is meaningless (less than 0 or greater than $N$)
causes a fatal error.  Movement to a label causes a forward scan through the
structure starting from (but not including) the current position of the
element pointer; thus it is typically wise to set the element pointer to 0
before attempting to move the element pointer to a label.  If the label is not
found, a fatal error occurs.
\begincode
typedef int elementIndex, label_ID;
void SPH_setElementPointer (elementIndex);
void SPH_offsetElementPointer (int delta);
void SPH_moveElementPointerToLabel (label_ID);
\endcode

\newpar
When a structure is open for editing, the application may inquire the
index of the current element:
\begincode
elementIndex SPH_inquireElementPointer (void);
\endcode

\newpar
The most common form of editing is simply the insertion of new elements into a
structure.  Whenever an element-generator function is called, the new element
is placed immediately after the current element, and the element pointer is
advanced to point to the new element.

\newpar
Label elements have integer names which must be unique within the 
structure owning it.  The following function generates a label element.

\begincode
void SPH_label (label_ID);   \elementgenerator
\endcode

\itemmm{NOTE:}
Throughout this document, each presentation of an element-generator routine is
``highlighted'' by the presence of this symbol:  \elementgenerator

\newpar
The following functions delete elements and automatically renumber the
survivors.  In all cases, after the deletion is made, the element pointer is
moved to point to the element immediately preceding the first element deleted.
The first function deletes the element indexed by the current value of the
element pointer.  The second function deletes the elements lying between, and
including, the elements specified by the two element identifiers.  The first
identifier must be less than the second one; a fatal error occurs otherwise.
The third function deletes the elements lying between, but not including, the
label elements specified.  The first label must appear in the structure before
the second one, and both must appear after the current value of the element
pointer; a fatal error occurs otherwise.

\begincode
void SPH_deleteElement (void);
void SPH_deleteElementsInRange (elementIndex first, elementIndex second);
void SPH_deleteElementsBetweenLabels (label_ID first, label_ID second);
\endcode

%\newpar
%It is possible to copy all the elements of a given structure into the open
%structure (immediately after the current element):
%\begincode
%void SPH_copyStructure (structure_ID);
%\endcode





\majorsect{3}{Coordinate systems}

\minorsect{3.1}{geometric data types}
The following data types are defined in order to simplify the storage and
specification of vectors, points, and matrices:

\begincode
typedef double point[3], vector[3];
typedef double matrix[4][4];
\endcode

\newpar
Vectors or points may be initialized using this function:

\begincode
double *SPH_defPoint (pt,  x, y, z)
double *pt;    \comment{pointer to first of three consecutive doubles}
double x, y, z;
\endcode




\minorsect{3.2}{viewing transformations}
The SPHIGS viewing system involves an intermediate coordinate system called the
VRC (Viewing Reference Coordinates).  This first transformation simply
reorients the world by specifying a new set of axes: UVN.  The matrix which
performs this is called the \itit{view-orientation matrix} and can be
calculated using the following function.  The final argument to the function
must be a pointer to a matrix (to be initialized by the function) allocated by
the application.

\begincode
void
SPH_evaluateViewOrientationMatrix
   (point view_ref_point, vector view_plane_normal, vector view_up_vector,
    matrix vo_matrix);
\endcode

\newpar
The next transformation sets up the view volume, which maps VRC to NPC
(Normalized Projection Coordinates).  To be more specific, it maps the contents
of the view volume to a paralleliped in NPC space.  (It is recommended, but not
enforced, that the rectangle lie wholly inside the NPC bounded space
[0,0]$\rightarrow$[1,1].)  The matrix which performs this is called the
\itit{view-mapping matrix}.

\begincode
void 
SPH_evaluateViewMappingMatrix
   (double umin, double umax, 
    double vmin, double vmax,   \comment{boundaries of window on view plane}
    int proj_type,        \comment{either PERSPECTIVE or ORTHOGRAPHIC}
    point proj_ref_point,   \comment{in uvn coordinates}
    double proj_front_clip_distance,
       double proj_back_clip_distance,  \comment{offsets from VRP on n axis }
    \comment{3D viewport: in this version, minz and maxz are ignored}
    double proj_NPCviewport_minx, double proj_NPCviewport_maxx,
    double proj_NPCviewport_miny, double proj_NPCviewport_maxy,
    double proj_NPCviewport_minz, double proj_NPCviewport_maxz,
    matrix vm_matrix);
\endcode

\newpar
It is very important to understand that the projection-reference point and the
window's boundaries (umin, umax, vmin, vmax) are specified NOT in WC, but as
offsets from the VRP that is set by the orientation matrix.  This means that in
order to perform an animation which involves only simple camera motion, with no
change in the ``focal length'' and no strange warpings, all one needs to do is
change the view-orientation matrix.  The prp will ``follow'' the vrp as the
view orientation is changed.

\newpar
Notice that there is no explicit way to specify focal length in this system.
The distance between the VRP and the PRP can be manipulated to achieve similar
results.  Be careful!  The $z$ coordinate of the PRP must be positive!  Also,
if you specify the PRP in such a way that a line between it and the center of
the view plane is not perpindicular to the view plane, shearing will occur.

\newpar
The setting of an entry in the view table requires specification of both the
matrices as well as a re-specification of the NPC viewport (again, with minz
and maxz ignored):

\begincode
void
SPH_setViewRepresentation
   (int view_index, 
    matrix vo_matrix, matrix vm_matrix,
    double clip_NPCviewport_minx, double clip_NPCviewport_maxx, 
    double clip_NPCviewport_miny, double clip_NPCviewport_maxy,
    double clip_NPCviewport_minz, double clip_NPCviewport_maxz);
\endcode


\newpar
The background color for a view's rectangular region of the screen is white by
default, but you may change it (on a per-view basis):

\begincode
void SPH_setViewBackgroundColor (int viewindex, int color);
\endcode





\minorsect{3.3}{modeling transformations}
Each structure has its own modeling coordinate system (MCS); primitives
specified within it are placed in its MCS.  When the execution of a structure
(during traversal) begins, its local modeling transformation is initialized to
the ``identity'' transformation.  When a primitive element is executed, its raw
coordinates are transformed by the current value of the local modeling
transformation in order to place it within the MCS.  When a structure-execution
element is executed, the MCS of the subordinate structure is mapped into the
local MCS using the local modeling transformation: thus the image of the
subordinate network is transformed as a single entity to be placed within the
local MCS.

\newpar
The following function generates a structure element which, when executed,
affects the local modeling transformation matrix, either by replacing
(assigning) it or by concatenating it with a given matrix.

\begincode
typedef enum \lb{}ASSIGN, PRECONCATENATE, POSTCONCATENATE\rb updateType;
void SPH_setModelingTransformation (matrix mat, updateType);  \elementgenerator
\endcode

\newpar
An application can use the following functions for creating a matrix to be
stored or to be used to set a modeling transformation.  Rotation, translation,
scaling, and compositions thereof are supported.  Rotation angles are specified
in degrees, positive angles representing counter-clockwise rotation.  In all
functions, the last parameter specifies the application-allocated area (large
enough to store a 4-by-4 array of \ttit{double}s) in which the function is to
place the calculated matrix.

\begincode
void SPH_scale (double scaleX, double scaleY, double scaleZ,  matrix result) 
void SPH_rotateX (double angleDegrees,  matrix result)
void SPH_rotateY (double angleDegrees,  matrix result)
void SPH_rotateZ (double angleDegrees,  matrix result)
void SPH_translate 
     (double deltaX, double deltaY, double deltaZ,  matrix result)

void SPH_composeMatrix (matrix mat1, matrix mat2,  matrix result)
\endcode

\newpar
In the textbook's Pascal code, a matrix could be calculated and made into an
element in one statement, because Pascal can return arrays:
\begincode
   SPH_setModelingTransformation (SPH_scale(5.0,3.0,1.0), ASSIGN);
\endcode
\newpar
It was not possible to design an elegant method in ANSI C for the calculation
routines to return a matrix in a manner that would allow the same convenience.
Thus, creating a transformation element requires two C statements (unless the
matrix is already available):
\begincode
   SPH_scale (5.0, 3.0, 1.0,  mat);
   SPH_setModelingTransformation (mat, ASSIGN);
\endcode
\newpar
The SPHIGS header file \ttit{sphigs.h} defines a macro called
\ttit{SPH\_setModXform} that can come to the rescue if you abhor the 
two-statement sequence.  The macro assumes that you have declared and are using
a matrix called \ttit{temp\_matrix}.  Here I show the usage of the macro for
the creation of a scale element:
\begincode
   SPH_setModXform (SPH_scale(5.0, 3.0, 1.0, temp_matrix), ASSIGN);
\endcode



\majorsect{4}{Color and Shading}
SPHIGS provides a device-independent method for dealing with color.  An
application can load the SPHIGS color table without concern for the number of
colors actually available, and can assign colors to objects equally carefree.
SPHIGS maps unavailable entries to white (for interiors) or black (for lines,
text, markers, etc.).  Moreover, when LIT\_FLAT rendering is used, SPHIGS
simulates shading (by using bitmap patterns) when it is not possible to use
true colors for the shading.

\newpar
The total number of available colors is dependent upon the number of planes
requested via the third parameter to
\cmd{SPH\_begin}, and on the capabilities of the underlying hardware.  
See the SRGP reference manual for information on color planes.

\newpar
SPHIGS divides up the available colors in this manner: The first two colors are
fixed at white (0) and black (1); the application may not modify these entries.
The next $C$ entries (2 through $(C+2)$) are called
\itit{custom colors} and are application-settable.
The first $F$ custom colors are called
\itit{flexicolors}.  When a flexicolor is assigned to the interior of a facet
or fill area, SPHIGS displays an appropriately darkened shade of that color
when LIT\_FLAT rendering mode is used.  When a non-flexicolor is assigned to a
facet or fill area, SPHIGS must simulate shading by using bitmap patterns.

\newpar
The values of $F$ and $C$ are calculated by SPHIGS based on the total number of
available SRGP colors and on the value of the 4'th parameter of
\cmd{SPH\_begin}: the number of shades you wish to be created for 
each flexicolor.  Obviously: the larger the number of shades per flexicolor,
the fewer flexicolors SPHIGS will be able to provide.

\newpar
After \cmd{SPH\_begin} returns, you can inquire the values of $F$ and $C$ by
examining these global variables: \ttit{NUM\_OF\_FLEXICOLORS} and 
\ttit{NUM\_OF\_APPL\_SETTABLE\_COLORS}.

\newpar
Currently, SPHIGS only provides one routine for loading the color table:

\nextsynopsis
void SPH_loadCommonColor (int colorindex, char *colorname);
\endsynopsis
For information on the second parameter, see the SRGP reference manual.  When
you load a color into a flexicolor entry, SPHIGS automatically generates a
range of shades for that color.  For this reason, you must not bypass this
routine by calling SRGP directly.

\newpar
SPHIGS renders a lit-flat view using a simple lighting model using a single
point light source (specified in UVN coordinates, and thus attached to the
camera and mobile as the camera is mobile) and Lambertian reflection.  Ambient
light is automatically extant as well.  No light-source attenuation is
considered to exist, and surfaces are not self-occluding.  Because of these
restrictions, best results occur when the light source is kept well away from
the scene's objects themselves.  The default position of the light source is
above and behind the camera at a distance approximating infinity; it thus acts
as a ``sun'' simulator.



\majorsect{5}{Creation of Graphics Objects}



\minorsect{5.1}{polyLine}
\begincode
SPH_polyLine (int vertex_count, point *vertices) \elementgenerator
\endcode

\newpar
Attributes affecting the polyLine primitive:
\begincode
SPH_setLineStyle (int value)  \elementgenerator  \comment{See SRGP manual.}
SPH_setLineColor (int value)  \elementgenerator
SPH_setLineWidthScaleFactor (double scale_factor)  \elementgenerator
\endcode



\minorsect{5.2}{polyMarker}
\begincode
SPH_polyMarker (int vertex_count, point *vertices) \elementgenerator
\endcode

\newpar
Attributes affecting the polyMarker primitive:
\begincode
SPH_setMarkerStyle (int value)  \elementgenerator  \comment{See SRGP manual.}
SPH_setMarkerColor (int value)  \elementgenerator
SPH_setMarkerSizeScaleFactor (double scale_factor)  \elementgenerator
\endcode



\minorsect{5.3}{text}
Only the origin is affected by modeling and viewing transformations;
the text itself is always horizontal, aligned with the virtual screen window.
\begincode
SPH_text (point origin, char *str) \elementgenerator
\endcode

\newpar
The attributes affecting text are like their SRGP counterparts.  In fact, you
must call \ttit{SRGP\_loadFontTable} to load fonts.
\begincode
SPH_setTextFont (int font_index)  \elementgenerator 
SPH_setTextColor (int color_index) \elementgenerator
\endcode

\newpar
\boldit{NOTE: In this version of SPHIGS, text and lines are not 
sorted spatially with solid objects, so it is possible for a text or line
object to be obscured by a polyhedron or fill area that is actually behind it,
when rendered in LIT\_FLAT mode.}



\minorsect{5.4}{fill area}
A fill area must be convex and planar; SPHIGS does not attempt to verify either
of these conditions.  Like polyhedra facets (described next), the order in
which you specify the vertices determines which side is ``outside''.  Only the
outside side is visible in non-wireframe modes.
\boldit{Warning:  in this version of SPHIGS, fill areas are known to be buggy
in LIT\_FLAT mode.}
\begincode
SPH_fillArea (int vertex_count, point *vertices) \elementgenerator
\endcode

\newpar
Attributes that affect the appearance of both fill-area and polyhedron objects:

\begincode
SPH_setInteriorColor (int color_index) \elementgenerator
SPH_setEdgeColor (int color_index) \elementgenerator
SPH_setEdgeStyle (int value) \elementgenerator  \comment{same values as for line style}
SPH_setEdgeFlag (int value) \elementgenerator  \comment{EDGE_VISIBLE or EDGE_INVISIBLE}
SPH_setEdgeWidthScaleFactor (double scale_factor) \elementgenerator
\endcode

\newpar
See section 4 for a description of the color-index attribute.




\minorsect{5.5}{polyhedron}
To create a polyhedron element, you present a complete list of the vertices,
implicitly indexed from 0 to $(vcount-1)$.  You describe the facets by
presenting a single array of numbers (SPHIGS data type \ttit{vertex\_index}
that actually stores a concatenated set of facet descriptions.  Each facet
description is a sequence of (\itit{V}+1) numbers, where \itit{V} is the number
of vertices in the facet.  The first \itit{V} numbers are indices into the
vertex list; the last number is (-1) and acts as a sentinel ending the facet
specification.  The vertex indices for a facet must be presented in
counterclockwise order (as seen when looking at the facet's ``outside''
face).  Because each facet must be a closed polygon, the first vertex in the
list is implicitly the last as well.

\newpar
The data type \ttit{vertex\_index} must be used by the application programmer
in order to guarantee future compatibility.  It is of course \ttit{typedef}'ed
to either a short or an int in the \ttit{sphigs.h} file.

\newpar
\boldit{Note: In this beta version of SPHIGS, FACETS MUST BE CONVEX!}

\begincode
void SPH_polyhedron   \elementgenerator
   (int vertex_count, int facet_count,
    point *vertices,  vertex_index *facets);
\endcode

\newpar
The appearance of a polyhedron is affected by the same attributes that affect
the fill-area primitive.



\minorsect{5.6}{rendering modes}
SPHIGS currently supports only two of the rendering modes described in the
textbook.  The rendering mode is set by the following function:

\begincode
SPH_setRenderingMode (int value)  \comment{WIREFRAME_RAW, WIREFRAME (default), LIT_FLAT}
\endcode

%%%%% I REMOVED GOURAUD AND FLAT

\newpar
The raw wireframe mode renders without performing hidden-surface elimination or
clipping.  Because of this, strange results (and lots of warning messages)
occur if objects lie behind the camera.  The default mode (WIREFRAME) performs
clipping and hidden-surface elimination, but only draws edges.  The most
expensive mode draws surfaces as filled polygons whose colors are determined by
lighting/shading algorithms.  (See section 4 of this reference manual for a
complete description.)  In this version of SPHIGS, it is recommended that only
fill areas and polyhedra be posted to views being rendered in LIT\_FLAT mode.
See section 0 for a more detailed warning.


\minorsect{5.7}{execution of subordinate structures}
This function inserts a structure-execution element into the currently open
structure.  The structure referenced by the argument need not already be
defined, as explained previously, for all unknown structures are implied empty
structures.
\begincode
void SPH_executeStructure (int structureIndex) \elementgenerator
\endcode



\majorsect{6}{Dynamic Invisibility and Highlighting}
NOT AVAILABLE IN THIS VERSION!!

%%%During traversal, an attribute called the \itit{name set} is maintained.  This
%%%set may contain any integers that lie between 0 and \ttit{MAX\_NAME}.  The
%%%following elements add and delete names from the name set during traversal:
%%%\begincode
%%%SPH_addToNameSet (name) \elementgenerator      \itit{you can only add one name at a time}
%%%SPH_deleteFromNameSet (name) \elementgenerator \itit{you can only delete one name at a time}
%%%SPH_emptyNameSet () \elementgenerator          \itit{sets name set to empty set}
%%%\endcode
%%%
%%%\newpar
%%%There are two filters that control highlighting and visibility during
%%%traversal.  A filter is simply a set of names: e.g., any primitives whose name
%%%set contains $X$ will not be visible if the invisibility filter contains $X$.
%%%These filters are not controlled by elements in the mode; rather, application
%%%sets them whenever it wants to modify the visibility or highlighting state of
%%%any part of the model.  When any filter is changed, the screen is updated to
%%%reflect the new state.
%%%
%%%\begincode
%%%SPH_addToHighlightFilter (name)
%%%SPH_removeFromHighlightFilter (name)
%%%SPH_addToInvisibilityFilter (name)
%%%SPH_removeFromInvisibilityFilter (name)
%%%\endcode
%%%







\majorsect{7}{Input}

\minorsect{7.1}{control of input devices}
The locator measure is similar to that of the SRGP locator, but the position is
a 3D NPC coordinate (with $z=0$), and the index of the non-empty view (i.e.,
having at least one posted root) with the highest priority (i.e. index)
that encloses the position is also returned:
\begincode
typedef struct \lb
    point position;
    int   view_index;
    int   button_chord[3];
    int   button_of_last_transition;
\rb locator_measure;
\endcode

\newpar
Control of the input devices is performed a la SRGP.  Any positions are 3D
NPC points ($z$ ignored) instead of 2D PDC points.

\begincode
#define SPH_setInputMode SRGP_setInputMode
#define SPH_waitEvent SRGP_waitEvent
#define SPH_getKeyboard SRGP_getKeyboard
#define SPH_sampleKeyboard SRGP_sampleKeyboard
#define SPH_setKeyboardProcessingMode SRGP_setKeyboardProcessingMode
#define SPH_setKeyboardEchoColor SRGP_setKeyboardEchoColor
#define SPH_setKeyboardEchoFont SRGP_setKeyboardEchoFont
#define SPH_setKeyboardMeasure SRGP_setKeyboardMeasure
#define SPH_setLocatorEchoCursorShape SRGP_setLocatorEchoCursorShape
#define SPH_setLocatorButtonMask SRGP_setLocatorButtonMask

void SPH_getLocator (locator_measure*);
void SPH_sampleLocator (locator_measure*);
void SPH_setLocatorMeasure (point position);
void SPH_setKeyboardEchoOrigin (point position);
\endcode


\minorsect{7.2}{pick correlation}
The NPC point returned from the locator can be sent to the pick-correlation
utility: 

\begincode
void SPH_pickCorrelate (point npc_position, int view_index, 
			pickInformation *pickinfo);
\endcode

\newpar
The information is returned in a variable of type \ttit{pickInformation}:

\begincode
typedef
   struct \lb
     int structureID;
     int elementIndex;
     int elementType;   \comment{symbolic constants in elementType.h}
   \rb pickPathItem;
typedef pickPathItem pickPath[MAX_HIERARCHY_LEVEL];
typedef struct \lb
     int pickLevel;
     pickPath path;
   \rb pickInformation;
\endcode

\newpar
When no primitive is close enough to the cursor position, the value of the
pickLevel field is returned as 0.  When pickLevel is greater than zero, it
specifies the length of the path from the root to the picked primitive.  In
this latter case, elements [0] through [pickLevel-1] 
of the path array return the
identification of the structure elements involved in the path.  
Of course,
elements [0] through [pickLevel-2] will always be structure-execution elements,
whereas the [pickLevel-1] element will always be an output primitive.  For each
element, the information presented is: its ID, its index within its parent
structure, a code presenting the element's type (e.g.,
ELTYP\_\_EXECUTE\_STRUCTURE, 
ELTYP\_\_POLYHEDRON), and the pick ID of the element.

\newpar
The pick ID is an attribute that is local to a structure (not inherited),
begins with the value 0, and changed by elements created via:

\begincode
SPH_setPickIdentifier (int pick_ID);  \elementgenerator
\endcode




\majorsect{8}{Control of Table Sizes}
The tables that store views and structures have default sizes that in many
cases are acceptable.  You may, however, choose to reduce the size of a table
to save memory (if you're working on a Mac Plus, for instance) or increase the
size of a table if you need more entries.  You must change the size of a table
\itit{before} you initialize SPHIGS!

\newsynopsis
void SPH_setMaxStructureID (int);
void SPH_setMaxViewIndex (int);
\endsynopsis
See \cmd{sphigs.h} for the defaults for these sizes.


\bye


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
